﻿using System;
using System.Collections.Generic;
using System.Linq;
using IloveRSS.Models.DataMap;
using IloveRSS.Models.VO;
using IloveRSS.Models.Logic;
using System.Web.Security;

namespace IloveRSS.Models
{
    public class DataManager
    {
        public ILoveRSSDataContext dataContext;

        private MembershipMapRepository membershipRepository;

        private SitesMapRepository sitesRepository;

        private ChannelsMapRepository channelsRepository;

        private TagsMapRepository tagsRepository;

        private FormerRss rssBuilder;

        #region Property.
        public MembershipMapRepository MembershipRepository
        {
            get
            {
                if (null == membershipRepository)
                {
                    membershipRepository = new MembershipMapRepository(dataContext);
                }
                return membershipRepository;
            }
        }

        public SitesMapRepository SitesRepository
        {
            get
            {
                if (null == sitesRepository)
                {
                    sitesRepository = new SitesMapRepository(dataContext);
                }
                return sitesRepository;
            }
        }

        public ChannelsMapRepository ChannelsRepository
        {
            get
            {
                if (null == channelsRepository)
                {
                    channelsRepository = new ChannelsMapRepository(dataContext);
                }
                return channelsRepository;
            }
        }

        public TagsMapRepository TagsRepository
        {
            get
            {
                if (null == tagsRepository)
                {
                    tagsRepository = new TagsMapRepository(dataContext);
                }
                return tagsRepository;
            }
        }
        #endregion

        //
        // TODO: Exceptiones
        //
        public DataManager(String connectionString)
        {
            dataContext = new ILoveRSSDataContext(connectionString);
            rssBuilder = FormerRss.GetInstance();
        }

        public String GetRss(int channelID)
        {
            return GetRss(channelID, String.Empty);
        }

        public String GetRss(int channelID, String link)
        {
            var channel = ChannelsRepository.GetChannelByID(channelID);
            if(channel != null)
            {
                return rssBuilder.Form(channel, link);
            }
            else
            {
                return null;    
            }
        }

        public List<ChannelVO> GetChannelsByUser(String userName)
        {
            return GetChannelsVO(MembershipRepository.GetChannelsByUserName(userName));
        }

        public List<ChannelVO> GetChannelsByPopular()
        {
            return GetChannelsVO(ChannelsRepository.GetChannelsByRate());
        }
        
        /// <summary>
        /// orders by number of equals with tags
        /// ignores case
        /// </summary>
        /// <param name="tags"></param>
        /// <returns>
        /// always returns all channels
        /// </returns>
        public List<ChannelVO> FindChannelsByTags(List<String> tags)
        {
            return GetChannelsVO(ChannelsRepository.GetChannelsByTags(tags));
        }

        public void SetFavouriteChannel(String userName, int channelID)
        {
            if(null != userName)
            {
               MembershipRepository.SetFavouriteChannel(userName, channelID);
            }
        }

        public void ResetFavouriteChannel(String userName)
        {
            if(null != userName)
            {
                MembershipRepository.ResetFavouriteChannel(userName);
            }
        }

        public ChannelVO GetFavouriteChannel(String userName)
        {
            Channels favouriteChannel = MembershipRepository.GetFavouriteChannel(userName);
            if(null != favouriteChannel)
            {
                return GetChannelVO(favouriteChannel);
            }
            else
            {
                return null;
            }
        }

        public void SignIn(String userName, int channelID)
        {
            var channel = ChannelsRepository.GetChannelByID(channelID);
            MembershipRepository.SignIn(userName, channel);
        }

        public void SignOut(String userName, int channelID)
        {
            var channel = ChannelsRepository.GetChannelByID(channelID);
            MembershipRepository.SignOut(userName, channel);
        }

        public List<String> GetAllTags()
        {
            var tags = TagsRepository.GetAllTags();
            return (null != tags) ? tags.Select(item => item.Text).ToList<String>() : null;
        }

        public List<String> GetAllSites()
        {
            var sites = SitesRepository.GetAllSites();
            return (null != sites) ? sites.Select(site => site.SiteURL).ToList<String>() : null;
        }

        public String GetAllSitesByPrefix(string prefix)
        {
            var sites = SitesRepository.GetAllSites();
            List<String> list = (null != sites) ? sites.Select(site =>
            {
                if (site.SiteURL.StartsWith(prefix)) return site.SiteURL;
                else return "";
            }).ToList<String>() : null;
            String result = "";
            foreach (String siteName in list)
            {
                if (siteName!="")
                {
                    result += siteName + "\n\r";
                }
            }
            return result;
        }

        public void AddChannel(String userName, String channelName,String description, bool visible, IEnumerable<String> tagsText, IEnumerable<String> sites)
        {
            aspnet_Users user = MembershipRepository.GetUserByName(userName);
            if (null != user)
            {
                Channels channel = ChannelsRepository.Add(channelName, visible);
                channel.Description = description;
                foreach (String tagText in tagsText)
                {
                    Tags tag = TagsRepository.Add(tagText);
                    channel.Tags.Add(tag);
                }
                foreach (var siteURL in sites)
                {
                    Sites site = SitesRepository.AddSite(siteURL);
                    channel.Sites.Add(site);
                }
                user.Channels.Add(channel);
                dataContext.SubmitChanges();
                SignIn(userName, channel.ID);
            }
        }

        public bool DeleteUser(String userName)
        {
            try
            {
                return Membership.DeleteUser(userName);
            }
            catch (Exception)
            {
                return false;
            }
        }

        private ChannelVO GetChannelVO(Channels channel)
        {
            return new ChannelVO(channel.ID,channel.ChannelName, channel.Description, channel.Tags, ChannelsRepository.GetRate(channel.ID));
        }

        private List<ChannelVO> GetChannelsVO(IEnumerable<Channels> channels)
        {
            return channels.Select(GetChannelVO).ToList();
        }

        public bool IsVisibleByUser(int id, string userName)
        {
            var channel = ChannelsRepository.GetChannelByID(id);
            if (null != channel)
            {
                return MembershipRepository.IsVisibleByUser(channel, userName);
            }
            else
            {
                return false;
            }
        }
    }
}